package com.ricchieri.manage.bean;

import java.sql.Date;

import org.apache.log4j.Logger;
import org.jasypt.util.password.ConfigurablePasswordEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import com.ricchieri.common.CustomAuthenticationToken;
import com.ricchieri.model.User;
import com.ricchieri.service.interf.IUserService;

/**
 * A custom authentication manager that allows access if the user details
 * exist in the database and if the username and password are not the same.
 * Otherwise, throw a {@link BadCredentialsException}
 */
public class CustomAuthenticationManager implements AuthenticationManager {
	
	protected static Logger logger = Logger.getLogger("service");

	@Autowired
	IUserService userService;
	
	@Autowired
	ConfigurablePasswordEncryptor encriptor;

	public Authentication authenticate(Authentication auth)
			throws AuthenticationException {

		logger.debug("Performing custom authentication");
		User user = null;
		
		try {
			user = userService.getUserByUsername(auth.getName());
		} catch (Exception e) {
			logger.error("User does not exists!");
			throw new BadCredentialsException("usernamePasswordWrong");
		}
				
		if(user.getLoginAttemp() > 2){
			logger.error("userBlocked");
			throw new BadCredentialsException("userBlocked");
		}else{			

			String encriptPassword = encriptor.encryptPassword((String) auth.getCredentials());
			if (!user.getPassword().equals(encriptPassword)) {
				setLoginAttempUser(user);
				
				logger.error("Wrong password");
				throw new BadCredentialsException("usernamePasswordWrong");
			}
			
			user.setLastLogin(new Date(System.currentTimeMillis()));
			user.setLoginAttemp(0);
			getUserService().updateUser(user);
			logger.debug("User details are good and ready to go");
			
			return new CustomAuthenticationToken(
					auth.getName(), 
					auth.getCredentials(), 
					user.getAuthorities(),
					user);
		}
	}

	public IUserService getUserService() {
		return userService;
	}

	public void setUserService(IUserService userService) {
		this.userService = userService;
	}

	public ConfigurablePasswordEncryptor getEncriptor() {
		return encriptor;
	}

	public void setEncriptor(ConfigurablePasswordEncryptor encriptor) {
		this.encriptor = encriptor;
	}
	
	private void setLoginAttempUser(User user){
		user.setLoginAttemp(user.getLoginAttemp() + 1);
		getUserService().updateUser(user);
	}
}
